/**
 * 给定A和C，再给定N对字符串
 * 求满足条件的i，Bi0是A的子串，C是Bi1的子串
 * 字符串匹配。B0用AC自动机，B1用KMP即可
 * Fail树没有问题，打标记有问题，dfs也有问题
 * 改完以后AC
 * KMP模板也有问题，这里用了KMPCount，没有问题
 * KMP模板改对了
 */
#include <bits/stdc++.h>
using namespace std;
#include <bits/extc++.h>
using namespace __gnu_pbds;

struct Aho{

enum{ALPHA_SIZE=26}; // 字母种类

vector<array<int, ALPHA_SIZE>> Trie;
vector<int> Flag; // 记录末端对应的索引
vector<int> Fail; 
vector<vector<int>> G; // Fail树

array<int, 256> L2I;

void init(int capa=1E6){
    for(int i=0;i<ALPHA_SIZE;++i){
        L2I[i + 'a'] = i;
    }

    Trie.clear();
    Trie.reserve(capa);
    Fail.clear();
    Fail.reserve(capa);
    Flag.clear();
    Flag.reserve(capa);
    G.clear();
    G.reserve(capa);
    
    SCnt = 0;
    ErrorState = _newState();
    StartState = _newState();

    return;
}

template<typename IT=string::iterator>
void insert(IT s, IT e, int idx){
    int state = StartState;
    for(auto it=s;it!=e;++it){
        int sn = L2I[(int)*it];
        if(0 == Trie[state][sn]){
            Trie[state][sn] = _newState();
        }
        state = Trie[state][sn];
    }
    Flag[state] = idx;
    return;
}

void buildAC(){
    Fail[StartState] = StartState;
    queue<int> q;
    for(int i=0;i<ALPHA_SIZE;++i){
        int & state = Trie[StartState][i];
        if(state){
            Fail[state] = StartState;
            q.push(state);
            G[StartState].push_back(state);
        }else{
            state = StartState;
        }
    }

    while(not q.empty()){
        int u = q.front(); q.pop();
        for(int i=0;i<ALPHA_SIZE;++i){
            int & state = Trie[u][i];
            if(state){
                Fail[state] = Trie[Fail[u]][i];
                q.push(state);
                G[Trie[Fail[u]][i]].push_back(state);
            }else{
                state = Trie[Fail[u]][i];
            }
        }
    }

    return;
}

template<typename IT = string::iterator>
void query(IT s, IT e, std::function<void(int, int)> f){
    int state = StartState;
    for(auto it=s;it!=e;++it){
        int sn = L2I[(int)*it];
        state = Trie[state][sn];
        f(state, Flag[state]);        
    }
    return;
}

int _newState(){
    Trie.push_back({0});
    Fail.push_back(0);
    Flag.push_back({});
    G.push_back({});
    return SCnt++;
}

int StartState;
int ErrorState;
int SCnt;

};

template<typename IT = const char *>
void calcKMPNext(IT begin, int n, vector<int> & next) {
    next.assign(n + 1, 0); 
    int k = -1, i = 0;
    next[0] = -1;
    while(i < n){
        while(k >= 0 and *(begin + i) != *(begin + k)) k = next[k];
        ++i, ++k;
        if(i == n) break;
        next[i] = *(begin + i) == *(begin + k) ? next[k] : k;
    }
    next[n] = k;
    return;
}

template<typename IT = const char *>
int KMPCount(IT t, int tn, IT p, int pn, const vector<int> & next, vector<int> & pos){
    assert(pn + 1 == next.size());
    pos.clear();
    if(tn < pn) return 0;
    int tp = 0, pp = 0, ret = 0;
    while(tp < tn){
        if(-1 == pp or *(t + tp) == *(p + pp)) ++tp, ++pp;
        else pp = next[pp];
        if(pp == pn){
            ret += 1; pp = next[pn];
            pos.emplace_back(tp - pn);
        }
    }
    return ret;
}

using llt = long long;
using vi = vector<int>;
using vll = vector<llt>;
using pii = pair<int, int>;

Aho AC;

int N;
string A, C;
vector<array<string, 2>> B;
vi Ans;
map<string, int> Map;
vi Pos;
vi Next;
vi Src;
vi D;

void dfs(int u, int p){
    for(auto v : AC.G[u]){
        if(v == p) continue;
        dfs(v, u);
        D[u] |= D[v];      
    }
    if(AC.Flag[u]) Ans[AC.Flag[u]] = D[u];
    return;
}

void proc1(){
    AC.init();
    Pos.assign(N + 1, 0);
    Map.clear();
    for(int i=1;i<=N;++i){
        auto it = Map.find(B[i][0]);
        if(it == Map.end()){
            it = Map.insert(it, {B[i][0], i});
        }
        AC.insert(B[i][0].begin(), B[i][0].end(), Pos[i] = it->second);
    }
    AC.buildAC();

    D.assign(AC.Trie.size(), 0);
    AC.query(A.begin(), A.end(), [&](int state, int flag){D[state] = 1;});

    dfs(1, 0);

    for(int i=1;i<=N;++i)Ans[i] = Ans[Pos[i]];
    return;
}

void proc2(){
    calcKMPNext(C.begin(), C.length(), Next);
    for(int i=1;i<=N;++i){
        if(0 == Ans[i]) continue;

        auto & s = B[i][1];
        vector<int> pos;
        auto t = KMPCount(s.begin(), s.length(), C.begin(), C.length(), Next, pos);
        // cout << i << ", " << t << endl;
        if(0 == t) Ans[i] = 0;
    }
}

void work(){ 
    cin >> N;
    B.assign(N + 1, {});

    cin >> A >> C;
    for(int i=1;i<=N;++i) {
        cin >> B[i][0] >> B[i][1];
    }

    Ans.assign(N + 1, 0);
    proc1();
    proc2();

    int k = 1;
    while(k <= N and 0 == Ans[k]) k += 1;
    if(k == N + 1) return (void)(cout << endl);

    cout << k;
    for(int i=k+1;i<=N;++i){
        if(Ans[i]) cout << " " << i;
    }
    cout << endl;
	return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	
    int nofkase = 1;
	cin >> nofkase;
	while(nofkase--) work();
	return 0;
}